// static/front/js/csrf_ajax.js
// 对设置csrftoken的ajax进行封装，并添加token自动刷新功能

"use strict";

// Token管理器
let TokenManager = {
    isRefreshing: false,
    failedQueue: [],

    // 获取access token
    getAccessToken: function() {
        return localStorage.getItem('ACCESS_TOKEN');
    },

    // 获取refresh token
    getRefreshToken: function() {
        return localStorage.getItem('REFRESH_TOKEN');
    },

    // 保存tokens
    saveTokens: function(accessToken, refreshToken) {
        localStorage.setItem('ACCESS_TOKEN', accessToken);
        localStorage.setItem('REFRESH_TOKEN', refreshToken);
    },

    // 清除tokens
    clearTokens: function() {
        localStorage.removeItem('ACCESS_TOKEN');
        localStorage.removeItem('REFRESH_TOKEN');
        localStorage.removeItem('USER_KEY');
    },

    // 刷新token
    refreshToken: function() {
        let self = this;
        let refreshToken = this.getRefreshToken();

        if (!refreshToken) {
            return Promise.reject(new Error('No refresh token'));
        }

        return new Promise(function(resolve, reject) {
            // 使用原始的ajax方法避免拦截
            $.ajax({
                url: '/cmsapi/auth/refresh/',
                method: 'POST',
                headers: {
                    'Authorization': 'Bearer ' + refreshToken,
                    'X-CSRFToken': $("meta[name=csrf-token]").attr("content")
                },
                success: function(result) {
                    console.log(result)
                    if (result['code'] === 200) {
                        let newAccessToken = result['data']['access_token'];
                        self.saveTokens(newAccessToken, refreshToken);
                        resolve(newAccessToken);
                    } else {
                        self.clearTokens();
                        reject(new Error('Refresh token failed'));
                    }
                },
                error: function(xhr, status, error) {
                    self.clearTokens();
                    reject(new Error('Refresh token error: ' + (xhr.responseJSON ? xhr.responseJSON.message : error)));
                }
            });
        });
    },

    // 处理失败队列
    processQueue: function(error, token = null) {
        this.failedQueue.forEach(function(prom) {
            if (error) {
                prom.reject(error);
            } else {
                prom.resolve(token);
            }
        });

        this.failedQueue = [];
    }
};

let csrf_ajax = {
    "get": function(args) {
        args['method'] = "GET";
        this.ajax(args);
    },
    "post": function(args) {
        args['method'] = "POST";
        this.ajax(args);
    },
    "ajax": function(args) {
        // 保存原始的回调函数
        let originalSuccess = args.success || function() {};
        let originalError = args.error || function() {};

        // 设置csrftoken
        this._ajaxSetup();

        // 添加Authorization头
        let accessToken = TokenManager.getAccessToken();
        if (accessToken) {
            args.headers = args.headers || {};
            args.headers['Authorization'] = 'Bearer ' + accessToken;
        }

        // 保存原始参数用于重试
        let originalArgs = $.extend(true, {}, args);

        // 如果正在刷新token，将请求加入队列
        if (TokenManager.isRefreshing) {
            return new Promise((resolve, reject) => {
                TokenManager.failedQueue.push({
                    resolve: function(token) {
                        // 更新Authorization头
                        originalArgs.headers = originalArgs.headers || {};
                        originalArgs.headers['Authorization'] = 'Bearer ' + token;
                        // 重新发送请求
                        originalArgs.success = originalSuccess;
                        originalArgs.error = originalError;
                        $.ajax(originalArgs);
                        resolve();
                    },
                    reject: function(error) {
                        originalError(null, 'token_refresh_failed', error.message);
                        reject(error);
                    }
                });
            });
        }

        // 包装success回调以处理token过期
        args.success = function(result) {
            console.log(result)
            // 检查是否是token过期错误
            if (result && result['code'] === 401) {
                // 检查是否包含token_expired标识
                if (result['data'] && result['data']['token_expired']) {
                    // Token过期，需要刷新
                    handleTokenExpired(originalArgs, originalSuccess, originalError);
                    return;
                } else if (result['message'] && result['message'].includes('expired')) {
                    // 通过消息内容判断token过期
                    handleTokenExpired(originalArgs, originalSuccess, originalError);
                    return;
                }
            }
            // 正常响应
            originalSuccess(result);
        };

        // 包装error回调以处理401错误
        args.error = function(xhr, status, error) {
            // 检查是否是401错误
            if (xhr.status === 401) {
                let response = xhr.responseJSON || {};
                // 检查多种token过期标识
                if ((response['data'] && response['data']['token_expired']) ||
                    (response['message'] && response['message'].includes('expired')) ||
                    (response['message'] && response['message'].includes('Token'))) {
                    // Token过期，需要刷新
                    handleTokenExpired(originalArgs, originalSuccess, originalError);
                    return;
                }
            }

            // 其他错误
            originalError(xhr, status, error);
        };

        // 发送请求
        $.ajax(args);
    },
    "_ajaxSetup": function(args) {
        $.ajaxSetup({
            "beforeSend": function(xhr, settings) {
                if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
                    let csrftoken = $("meta[name=csrf-token]").attr("content");
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            }
        });
    }
};

// 处理token过期的函数
function handleTokenExpired(originalArgs, originalSuccess, originalError) {
    // 如果没有refresh token，直接清除并跳转到登录页
    if (!TokenManager.getRefreshToken()) {
        TokenManager.clearTokens();
        window.location = '/login/';
        originalError(null, 'unauthorized', 'No refresh token');
        return;
    }

    // 如果正在刷新token
    if (TokenManager.isRefreshing) {
        // 将请求加入队列
        TokenManager.failedQueue.push({
            resolve: function(token) {
                // 更新Authorization头
                let retryArgs = $.extend(true, {}, originalArgs);
                retryArgs.headers = retryArgs.headers || {};
                retryArgs.headers['Authorization'] = 'Bearer ' + token;
                // 重新发送请求
                retryArgs.success = originalSuccess;
                retryArgs.error = originalError;
                $.ajax(retryArgs);
            },
            reject: function(error) {
                originalError(null, 'token_refresh_failed', error.message);
            }
        });
        return;
    }

    // 开始刷新token
    TokenManager.isRefreshing = true;

    TokenManager.refreshToken().then(function(newAccessToken) {
        // 刷新成功，更新原始请求的Authorization头
        originalArgs.headers = originalArgs.headers || {};
        originalArgs.headers['Authorization'] = 'Bearer ' + newAccessToken;

        // 重新发送原始请求
        originalArgs.success = originalSuccess;
        originalArgs.error = originalError;
        $.ajax(originalArgs);

        // 处理队列中的其他请求
        TokenManager.processQueue(null, newAccessToken);
    }).catch(function(error) {
        console.error('Token刷新失败:', error);
        // 刷新失败，清除token并跳转到登录页
        TokenManager.clearTokens();
        window.location = '/login/';

        // 处理队列中的其他请求
        TokenManager.processQueue(error);

        originalError(null, 'token_refresh_failed', error.message);
    }).finally(function() {
        TokenManager.isRefreshing = false;
    });
}
